package com.snail.common.job.config;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.snail.common.core.constant.SecurityConstants;
import com.snail.common.core.domain.R;
import com.snail.common.core.utils.StringUtils;
import com.snail.common.job.constant.JobConstants;
import com.snail.common.job.context.JobContextHolder;
import com.snail.job.admin.core.dto.JobLoginDto;
import com.snail.job.admin.core.feign.RemoteJobService;
import com.snail.job.admin.core.model.XxlJobGroup;
import com.snail.job.admin.core.model.XxlJobInfo;
import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.List;
import java.util.stream.Collectors;

/**
 * xxl-job config
 *
 * @author Snail
 */
@Configuration
@EnableConfigurationProperties(XxlJobProperties.class)
public class XxlJobConfig {
    private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class);

    @Autowired
    private RemoteJobService remoteJobService;

    @Bean
    public XxlJobSpringExecutor xxlJobExecutor(XxlJobProperties properties) {
        logger.info(">>>>>>>>>>> xxl-job config init................");
        XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
        xxlJobSpringExecutor.setAdminAddresses(properties.getAdminAddresses());
        xxlJobSpringExecutor.setAppname(properties.getAppName());
        xxlJobSpringExecutor.setAddress(properties.getAddress());
        xxlJobSpringExecutor.setIp(properties.getIp());
        xxlJobSpringExecutor.setPort(properties.getPort());
        xxlJobSpringExecutor.setAccessToken(properties.getAccessToken());
        xxlJobSpringExecutor.setLogPath(properties.getLogPath());
        xxlJobSpringExecutor.setLogRetentionDays(properties.getLogRetentionDays());

        //获取注入的job信息
        logger.info(">>>>>>>>>>> xxl-job task init................");
        initJobInfo(properties);
        return xxlJobSpringExecutor;
    }

    private void initJobInfo(XxlJobProperties properties) {
        String jobInfoStr = JobContextHolder.get(JobConstants.LOCAL_KEY_JOB_INFO, String.class);
        if (StringUtils.isEmpty(jobInfoStr)) {
            return;
        }
        // 登录job认证
        if (!loginJobAdmin(properties)) {
            return;
        }
        // 登录成功后，注册执行器
        int groupId = registerJobGroup(properties);
        if(groupId == -1){
            return;
        }
        // 执行器注册成功后，注册定时任务
        List<XxlJobInfo> xxlJobInfos = JSONArray.parseArray(jobInfoStr, XxlJobInfo.class);
        xxlJobInfos.forEach(item -> item.setJobGroup(groupId));
        String  result = HttpUtil.post(properties.getAdminAddresses() + "/jobinfo/rpc/add", JSONArray.toJSONString(xxlJobInfos));
        JSONObject jsonObject = JSONObject.parseObject(result);
        if ((int) jsonObject.get("code") != R.SUCCESS) {
            logger.info(">>>>>>>>>>> xxl-job JobTask add fail................");
            logger.info(ObjectUtil.toString(jsonObject.get("msg")));
            return;
        }
        logger.info(">>>>>>>>>>> xxl-job JobTask add success................");
        // 删除  释放内存空间
        JobContextHolder.remove();
    }

    /**
     * 注册job执行器
     *
     * @param properties 配置属性
     */
    private int registerJobGroup(XxlJobProperties properties) {
        XxlJobGroup jobGroup = new XxlJobGroup();
        jobGroup.setAppname(properties.getAppName());
        jobGroup.setTitle(properties.getTitle());
        String result = HttpUtil.post(properties.getAdminAddresses() + "/jobgroup/rpc/add", JSON.toJSONString(jobGroup));
        JSONObject groupObject = JSONObject.parseObject(result);
        if ((int) groupObject.get("code") != R.SUCCESS) {
            logger.info(">>>>>>>>>>> xxl-job jobGroup add fail................");
            logger.info(ObjectUtil.toString(groupObject.get("msg")));
            return -1;
        }
        logger.info(">>>>>>>>>>> xxl-job jobGroup add success................");
        return (int) groupObject.get("data");
    }

    /**
     * 登录job admin平台
     *
     * @param properties 配置属性
     */
    private boolean loginJobAdmin(XxlJobProperties properties) {
        JobLoginDto dto = new JobLoginDto();
        dto.setUserName(properties.getUserName());
        dto.setPassword(properties.getPassword());
        // 登录结果
        String result = HttpUtil.post(properties.getAdminAddresses() + "/rpc/login", JSON.toJSONString(dto));
        JSONObject jsonObject = JSONObject.parseObject(result);
        if ((int) jsonObject.get("code") != R.SUCCESS) {
            logger.info(">>>>>>>>>>> xxl-job login fail................");
            logger.info(ObjectUtil.toString(jsonObject.get("msg")));
            return false;
        }
        logger.info(">>>>>>>>>>> xxl-job login success................");
        return true;
    }

}